package Gameplay.Enemy;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Rectangle;

import ADTs.PointADT;
import Gameplay.IsLiving;
import Gameplay.Level;
import Gameplay.OnScreenObject;
import Gameplay.Weapon.Weapon;
import Project.Constants;
import Project.Main;
import Project.MyGraphics;
import Project.SaveFile;

/**
 * This is an abstract class of a Enemy contains enemy's hp, 
 * enemy's maxhp, enemy's worthMoneyValue, enemy's location
 * and so on. Also this enemy class is responsible for 
 * accessing AI.
 * 
 * @author	Brian Wetherbee
 * 			Ryan McNamara
 * 			Zeng Yang
 *
 */
public abstract class Enemy extends OnScreenObject implements IsLiving{
	protected /*@ spec_public @*/ double HP;
	protected /*@ spec_public @*/ double maxHP;
	protected /*@ spec_public @*/ double moneyValue;
	public Weapon currWeapon;
	protected AI ai;
	
	/*@ public invariant value > 0;
	  @ public invariant enemyDamage > 0;
	  @*/
	public Enemy(PointADT location, double HP) {
		currWeapon = new Weapon(false);
		this.HP = HP;
		this.maxHP = HP;
		this.location = location.copy();
		this.setAcceleration(new PointADT(0,0));
		currLevel = (Level)Main.getCurrentUI();
		this.movementBounds =  new Rectangle(0,0,Constants.width,Constants.height - Level.barHeight);
	}
	
	public Enemy(PointADT location) {
		this(location, 10);
	}
	
	/*@ requires enemyHP <= 0;
	  @ ensures money = \old(money) + value
	  @*/
	public void Die() {
		SaveFile.getCurrentFile().setMoney(
				SaveFile.getCurrentFile().getMoney() + moneyValue);
		currLevel.removeFromState(this);
	}
	
	/*@ requires enemyHP > 0;
	  @ assignable enemyPoint;
	  @ ensures hasCommand = true;
	  @*/
	public void accessAI() {
		ai.move(this);
		ai.attack(this);
	}
	
	//To paint enemy's graphics.
	public void paint(Graphics g) {
			g.setColor(Color.blue);
			int x = (int)location.getX();
			int y = (int)location.getY();
			g.drawOval(x-getRadius(), y - getRadius(), getRadius()*2, getRadius()*2);
			//g.drawRect((int)location.getX()-radius,(int)location.getY()-radius,radius*2,radius*2);
			//g.drawRect(movementBounds.x, movementBounds.y, movementBounds.width, movementBounds.height);
			//super.paint(gg);
	}
	
	//To calculate the damaged caused by projectiles
	//from player.
	//@ requires damage >= 0;
	//@ ensures HP = (\old HP - damage);
	public void damage(double damage) {
		HP -= damage;
		if(HP <= 0)
			this.Die();
	}
	
	public double getEnemyValue() {
		return moneyValue;
	}

	public double getHP() {
		return HP;
	}
	
	public boolean move() {
		accessAI();
		if (currLevel.isIT()) {
			this.velocity.setX(-Level.itEnemySpeed);
		}
		boolean result = super.move();
		if(currLevel.isIT()){
			if(!result){
				currLevel.removeFromState(this);
			}
		}
		
		return result;
	}
	
	public double getMaxHP() {
		return this.getMaxHP();
	}

}
